/*
 * opint.java
 *
 * Created on July 8, 2002, 10:40 AM
 */

package opint;

import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.*;
import com.sun.net.ssl.*;
import javax.net.ssl.*;

/**
 *
 * @author  llaranje
 * @version 
 */
public class opint {
    static PrintWriter out;
    static BufferedReader in;
    static BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
    static String appname;
    static final String ruleofthumb = "4c6c14a5de1cacbdab5dcf71e0078c7f";

    /** Creates new opint */
    public opint() {
    }

    private static boolean connectToRedMan(String hostname, int port) {
        try {
            // Initialize the provider
            System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
            //java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); 
            
            // Get socket factory
            SSLSocketFactory sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
            //System.out.println("Obtained the default SSL socket factory");
            
            // Connect to RedMan
            //Socket so = new Socket(hostname, port);
            //System.out.println("Will try to connect to RedMan on host " + hostname 
            //                                           + ", port = " + String.valueOf(port));
            SSLSocket so = (SSLSocket) sslFact.createSocket(hostname, port);
            //System.out.println("Connected to RedMan on host " + hostname);
            so.setTcpNoDelay(true);
            so.setSoTimeout(100000);
            
            // Get I/O streams to talk to RedMan                
            in  = new BufferedReader(new InputStreamReader(so.getInputStream()));
            out = new PrintWriter(new OutputStreamWriter(so.getOutputStream()));

            return(true);
        }
        catch (ConnectException e) {
            System.out.println("RedMan not allowing connection: " + e.getMessage());
            return(false);
        }
        catch (SocketException e) {
            System.out.println("Could not connect to RedMan: " + e.getMessage());
            return(false);
        }
        catch (Exception e) {
            e.printStackTrace();
            return(false);
        }
    }
    
    private static boolean sendCommandToRedMan(String cmd) {
        try {              
            if (out != null) {
                String msg = "OPINT " + appname + " " + cmd;
                             
                // System.out.println("opint: msg to RedMan = " + msg); 
                out.println(msg);
                out.flush();
                return(true);
            }
            else System.out.println("opint: not connected to RedMan");
            return(false);
        }
        catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
            return(false);
        }
    }
    
     private static boolean checkWithRedMan() {
        try {              
            if (out != null) {
                String msg = "OPINT " + ruleofthumb;
                             
                //System.out.println("opint: user/passwd to RedMan = " + msg); 
                out.println(msg);
                out.flush();
                
            }
            else System.out.println("Not connected to RedMan");
            String resp = in.readLine();
            if ((resp == null) || (resp.length() == 0) || !resp.equals("ACK")) {
                System.out.println("Authentication failed - resp = " + resp); 
                return(false);
            }
            else {
                // System.out.println("Authentication suceeded");
                return(true);
            }
        }
        catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
            return(false);
        }
    }   
    
    private static String receiveResponse() {
        try {
            String resp = in.readLine();
            if (resp != null) return(resp);
            else if (resp == null) {
                System.out.println("Connection with RedMan timed out. Exiting ...");
                System.out.flush();
                System.exit(1);
            }
            else if (resp.length() == 0) {
                System.out.println("Zero-length response received from RedMan");
                System.out.flush();
                return(null);
            }
        }
        catch (InterruptedIOException e) {
            System.out.println("Request to RedMan timed out");
            System.out.flush();
            System.exit(1);
        }
        catch (Exception e) {
            String errorMsg = e.getMessage();
            System.out.println(errorMsg);
            System.out.flush();
            if (errorMsg.startsWith("Connection reset")) System.exit(1);
            return(null);
        }
        return(null);
    }
    
    private static void badCmdUsage() { 
        System.out.println("Invalid command");
        System.out.println("USAGE: <appname> <command>");
        System.out.println("       <command> := START | SHUTDOWN [-F] | ENABLE | DISABLE [-F] | INHIBIT | UNINHIBIT | RESTART [-F] | RELOAD [REDUNDANT] | SWITCH | QUERY | PRIMARY <hostname> | GETPID [<procname>] | ACTIVE | STANDBY");
        System.out.flush();
    }
    
    private static void badUsage() {
        System.out.println("USAGE: opint [<hostname>]");
        System.out.flush();
        System.exit(1);
    }
    
    private static String readCommand() {
        String token1 = " ", cmd = null, primaryhost = null;
        String procname = null;
        int port = 2200, numtokens = 0;
        boolean force = false;
        boolean backup = false;
        boolean redundant = false;
        
        try {
 
            cmd = sysin.readLine();
            // System.out.println(cmd);
            // System.out.flush();
            if (cmd.equalsIgnoreCase("EXIT")) return(cmd);
            StringTokenizer st = new StringTokenizer(cmd);
            numtokens = st.countTokens();
            if ((numtokens < 2) || (numtokens > 3)) {
                badCmdUsage();
                return(null);
            }
            
            appname = st.nextToken();
            cmd = st.nextToken();
            if ((numtokens == 2) && (cmd.equals("PRIMARY"))) { 
                badCmdUsage();
                return(null);
            }
            
            if (numtokens == 3) {                     // <appname> <cmd> -F
                if (cmd.equals("PRIMARY")) {          // <appname> RELOAD REDUNDANT
                    primaryhost = st.nextToken();     // <appname> PRIMARY <hostname>   
                    token1 = primaryhost;             // <appname> GETPID <procname>
                }                                     //   REDMAN  GETPID BACKUP
                else if (cmd.equals("GETPID")) {
                    token1 = st.nextToken();
                    if (appname.equals("REDMAN")) {                       
                        if (token1.equals("BACKUP")) backup = true;
                        else {
                            badCmdUsage();
                            return(null);
                        }
                    }
                    else procname = token1;
                }
                else if (cmd.equals("RELOAD")) {
                    token1 = st.nextToken();
                    if (token1.equals("REDUNDANT")) redundant = true;
                    else {
                        badCmdUsage();
                        return(null);
                    }
                }
                else {
                    token1 = st.nextToken();
                    if (token1.equals("-F")) force = true;
                    else {
                         badCmdUsage();
                         return(null);
                     }
                }
            }
        }   
        catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
            return(null);
        }           

        // System.out.println("Will process command: " + appname + " " + cmd + " " + token1);
        if (cmd.equals("PRIMARY")) cmd = cmd + " " + primaryhost;
        if (cmd.equals("GETPID")) {
            if (backup) cmd += " BACKUP";
            if (procname != null) cmd += " " + procname;
        }
        if (cmd.equals("RELOAD")) {
            if (redundant) cmd += " REDUNDANT";
        }
        if (force) cmd = cmd + "-F";
        
        // System.out.println("Command: '" + cmd + "'");
        
        if (!cmd.equals("START")      &&   !cmd.equals("SHUTDOWN")    &&
            !cmd.equals("ENABLE")     &&   !cmd.equals("DISABLE")     &&
            !cmd.equals("INHIBIT")    &&   !cmd.equals("UNINHIBIT")   &&
            !cmd.equals("SWITCH")     &&   !cmd.equals("RESTART")     &&
            !cmd.equals("TEST")       &&   !cmd.equals("UNTEST")      &&
            !cmd.equals("ACTIVE")     &&   !cmd.equals("STANDBY")     &&
            !cmd.equals("QUERY")      &&   !cmd.startsWith("RELOAD")  &&
            !cmd.equals("ACTIVE")     &&   !cmd.equals("STANDBY")     &&
            !cmd.equals("SHUTDOWN-F") &&   !cmd.equals("DISABLE-F")   &&
            !cmd.equals("RESTART-F")  &&   !cmd.startsWith("PRIMARY") &&
            !cmd.startsWith("GETPID"))                                    {
                badCmdUsage();
                return(null);
        }
        // System.out.println("Command '" + cmd + "' passed test");
        return(cmd);
    }
    
    public static void main (String args[]) {
        int port = 2200;
        String cmd = null, hostname = null;
        boolean goaway = false;
        
        if (args.length > 2) badUsage();
        
        try {
            hostname = InetAddress.getLocalHost().getHostName();
            if (args.length == 1) hostname = args[0];
        }   
        catch (UnknownHostException e) {
            System.out.println(e.getMessage());
            System.out.flush();
            System.exit(1);
        }           
       
        
        // Connect to RedMan        
        if (connectToRedMan(hostname, port)) {
            if (!checkWithRedMan()) {
                System.out.println("Unable to authenticate with RedMan");
                System.out.flush();
                System.exit(1);
            }
            do {
                System.out.println();
                System.out.print("RedMan " + "[" + hostname +"] > ");
                System.out.flush();
                cmd = readCommand();
                
                if (cmd == null) continue;
                
                if (cmd.equalsIgnoreCase("EXIT")) {
                    System.out.print("\n");
                    System.out.flush();
                    System.exit(0);
                }
                
               
                if (sendCommandToRedMan(cmd)) {

                    // System.out.println("Successfully sent command \"" + cmd + "\" to RedMan");
                    boolean respOK = false;

                    String resp = receiveResponse();
                    if (resp != null) {
                        if (resp.indexOf("RedMan exiting") >= 0) goaway = true;                           
                        System.out.println(resp);
                        System.out.flush();
                        respOK = true;
                    }
                    if (!respOK) {
                        System.out.println("RedMan did not respond. Exiting ...");
                        System.out.flush();
                        System.exit(1);
                    }
                    if (goaway) {
                        System.out.println("\nExiting opint ...\n");
                        System.out.flush();
                        break;
                    }
                }
                else {
                    System.out.println("Unable to send command to RedMan - Exiting opint ... \n");
                    System.out.flush();
                    System.exit(1);
                }
            } while (true);
        }
        else {
            System.out.println("Unable to connect to RedMan - Exiting opint ...\n");
            System.out.flush();
            System.exit(1);
        }
    }
}